package ThreadAndLambda.WaitAndNotify;

/*等待唤醒案例：线程之间的通信
 *   创建一个消费者线程： 告知生产者需要生产的种类和数量，调用wait方法，放弃cpu的执行，进入waiting状态（无限等待）
 *   创建一个生产者线程：花费时间进行生产，生产完成后调用notify方法，唤醒消费者
 *
 * 注意：
 *   生产者和消费者必须使用同步代码块包裹，保证等待和唤醒只能又一个在执行
 *   同步使用的锁对象必须保持唯一
 *   只有锁对象才能调用wait和notify方法
 *
 * Object中的方法
 *    void	wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前，导致当前线程等待。
 *    void	notify() 唤醒在此对象监视器上等待的单个线程。
 *       会继续执行wait方法之后的代码
 *
 * */
public class WaitAndNotify01 {
    public static void main(String[] args) {
        //创建锁对象
        Object obj = new Object();
        //创建消费者线程
        new Thread() {
            @Override

            public void run() {
                while (true) {
                    //保证等待和唤醒的线程只能一个在执行
                    synchronized (obj) {
                        System.out.println("提出要求");
                        try {
                            //调用wait进入无限等待状态
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //唤醒之后执行的代码
                        System.out.println("获得生产者的物品");
                        System.out.println("_____________________________");
                    }
                }
            }
        }.start();


        //创建一个生产者对象
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    //花费2秒时间生产
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //保证等待和唤醒的线程只能一个在执行
                    synchronized (obj) {
                        System.out.println("花费2秒，生产结束");
                        //生产结束结束唤醒消费者
                        obj.notify();
                    }
                }
            }
        }.start();
    }
}
